package com.millstein.tsinglog.advice;

import com.google.common.collect.ImmutableMap;
import com.millstein.tsinglog.commons.enums.ResultCode;
import com.millstein.tsinglog.exception.TsinglogException;
import com.millstein.tsinglog.model.vo.result.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
@Slf4j
public class WebExceptionHandler {

    // 使用EXCEPTIONS存放异常类型和错误代码的映射
    protected static ImmutableMap<Class<? extends Throwable>, ResultCode> EXCEPTIONS;

    //使用builder来构建一个异常类型和错误代码的异常
    protected static ImmutableMap.Builder<Class<? extends Throwable>, ResultCode> builder = ImmutableMap.builder();

    // 构建EXCEPTIONS的信息
    static {
        builder.put(HttpMessageNotReadableException.class, ResultCode.PARAM_TYPE_BIND_ERROR);
        builder.put(org.springframework.web.multipart.MaxUploadSizeExceededException.class, ResultCode.FILE_TOO_BIG);
        builder.put(org.springframework.web.bind.MethodArgumentNotValidException.class, ResultCode.CONTENT_VALID_FAILURE);
    }

    /**
     * 处理自定义异常。如果自定义异常需要跳转至出错界面的，需要在代码中进行手动跳转
     */
    @ExceptionHandler(TsinglogException.class)
    @ResponseBody
    public CommonResult dealWithTsinglogException(TsinglogException e) {
        log.error("发生异常：{}", e.getMessage(), e);
        return CommonResult.failure(e.getResultCode());
    }

    // 处理其他异常
    @ExceptionHandler(Exception.class)
    public String dealWithOtherException(Exception e, HttpServletRequest request) {
        log.error("发生异常：{}", e.getMessage(), e);
        if (EXCEPTIONS == null) {
            EXCEPTIONS = builder.build();
        }
        final ResultCode result = EXCEPTIONS.get(e.getClass());
        if (result != null) {
            request.setAttribute("code", result.getCode());
        } else {
            request.setAttribute("code", ResultCode.SERVER_OCCURS_ERROR.getCode());
        }
        return "error/500";
    }
}

